package com.wcy.controller.resource;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wcy.entity.*;
import com.wcy.entity.pageVo.ApiDescriptor;
import com.wcy.entity.pageVo.Column;
import com.wcy.entity.pageVo.ColumnConstructor;
import com.wcy.entity.pageVo.PageData;
import com.wcy.feign.resource.FeignLearningResourceService;
import com.wcy.feign.user.FeignUserCollectionService;
import com.wcy.feign.user.FeignUserLearningHistoryService;
import com.wcy.feign.user.FeignUserRatingService;
import com.wcy.feign.user.FeignUserService;
import com.wcy.recommend.MyCFRecommend;
import com.wcy.util.JwtTokenUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.*;

@RestController
public class LearningResourceController {
    @Resource
    private FeignLearningResourceService feignLearningResourceService;
    @Resource
    private FeignUserRatingService feignUserRatingService;
    @Resource
    private FeignUserCollectionService feignUserCollectionService;
    @Resource
    private FeignUserLearningHistoryService feignUserLearningHistoryService;
    @Resource
    private JwtTokenUtil jwtTokenUtil;

    @GetMapping("resource/recommend")
    public ResponseEntity<List<LearningResource>> getRecommendation(HttpServletRequest request){
        //user collection
        //recommend
        List<Integer> resourceIds = new ArrayList<>();
        List<UserRating> ratings = feignUserRatingService.getList().getBody();
        try {
            List<UserCollection> collections = feignUserCollectionService.getList().getBody();
            List<UserLearningHistory> history = feignUserLearningHistoryService.getList().getBody();
            System.out.println(ratings);
            System.out.println(collections);
            System.out.println(history);
            MyCFRecommend myCFRecommend = new MyCFRecommend(0.33d, 0.66d, 0.5d, 8);
            assert ratings != null;
            myCFRecommend.createUserMatrix(ratings, collections, history);
            resourceIds.addAll(myCFRecommend.recommend(jwtTokenUtil.getUserIdFromToken(jwtTokenUtil.getToken(request))));
            ratings.removeIf(e->resourceIds.contains(e.getResourceId()));
        } catch (Exception e) {
            System.out.println("推荐失败，转为热度推荐");
        }
        //推荐数量太少，根据热度推荐来推荐
        if(resourceIds.size()<8){
            int count = 8 - resourceIds.size();
            //根据评分进行排序
            //id,score
            assert ratings != null;
            Map<Integer, Double> map = new HashMap<>();
            for (UserRating rating : ratings) {
                map.put(rating.getResourceId(), map.getOrDefault(rating.getResourceId(), 0d) + rating.getRatingValue());
            }
            map.entrySet().stream().sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())).limit(count).forEach(entry -> resourceIds.add(entry.getKey()));
        }
        return feignLearningResourceService.getListByIds(resourceIds);
    }

    @GetMapping("resource/page")
    public ResponseEntity<PageData<LearningResource>> getPage(@RequestParam(defaultValue = "1") int pageNum,
                                                              @RequestParam(defaultValue = "10") int pageSize) {
        return ResponseEntity.ok(new PageData<>(LearningResource.class, Objects.requireNonNull(feignLearningResourceService.getPage(pageNum, pageSize).getBody()),  new ApiDescriptor("resource/add", "resource/update", "resource/delete",  "", "resource/list"), ColumnConstructor.create()));
    }

    @GetMapping("resource/list")
    public ResponseEntity<List<LearningResource>> getList() {
        return feignLearningResourceService.getList();
    }

    @GetMapping("resource/{id}")
    public ResponseEntity<LearningResource> get(@PathVariable("id") Integer id) {
        return feignLearningResourceService.get(id);
    }

    @PostMapping("resource/add")
    public ResponseEntity<Void> add(@RequestBody LearningResource learningResource) {
        return feignLearningResourceService.add(learningResource);
    }

    @PutMapping("resource/update")
    public ResponseEntity<Void> update(@RequestBody LearningResource learningResource) {
        return feignLearningResourceService.update(learningResource);
    }

    @DeleteMapping("resource/delete")
    public ResponseEntity<Void> delete(Integer id) {
        return feignLearningResourceService.delete(id);
    }

    @GetMapping("resource/user/page")
    public ResponseEntity<PageData<LearningResource>> getPageAuthor(@RequestParam(defaultValue = "1") int pageNum,
                                                                @RequestParam(defaultValue = "10") int pageSize) {
        Column c = new Column();
        c.setAllowEdit(false);
        return ResponseEntity.ok(new PageData<>(LearningResource.class, Objects.requireNonNull(feignLearningResourceService.getPageAuthor(pageNum, pageSize).getBody()),  new ApiDescriptor("resource/user/add", "resource/user/update", "resource/user/delete",  "", "resource/list"), ColumnConstructor.create()).overrideColumn("authorId",c));
    }

    @PostMapping("resource/user/add")
    public ResponseEntity<Void> addByAuthor(@RequestBody LearningResource learningResource) {
        feignLearningResourceService.addByAuthor(learningResource);
        return ResponseEntity.ok().build();
    }

    @PutMapping("resource/user/update")
    public ResponseEntity<Void> updateByAuthor(@RequestBody LearningResource learningResource){
        feignLearningResourceService.updateByAuthor(learningResource);
        return ResponseEntity.ok().build();
    }

    @DeleteMapping("resource/user/delete/{id}")
    public ResponseEntity<Void> deleteByAuthor(@PathVariable Integer id){
        feignLearningResourceService.deleteByAuthor(id);
        return ResponseEntity.ok().build();
    }

    @GetMapping("resource/search/page")
    public ResponseEntity<PageData<LearningResource>> getSearchPage(@RequestParam(defaultValue = "1") int pageNum,
                                                                    @RequestParam(defaultValue = "10") int pageSize) {
        return ResponseEntity.ok(new PageData<>(LearningResource.class,feignLearningResourceService.getPage(pageNum, pageSize).getBody(),  ApiDescriptor.empty(), ColumnConstructor.create()));
    }

    @GetMapping("resource/getByAuthor/{id}")
    public ResponseEntity<List<LearningResource>> getByAuthor(@PathVariable("id") Integer id) {
        return feignLearningResourceService.getByAuthor(id);
    }
}
